package org.batatasframework.support.searchable.result;

import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

import org.batatasframework.support.database.SelectedFieldCollection;
import org.batatasframework.support.database.spi.AbstractExecution;
import org.batatasframework.support.database.sql.field.SelectFragment;
import org.batatasframework.support.searchable.ResultHeadInfo;
import org.batatasframework.support.searchable.SearchableInputStream;


public abstract class AbstractResultStream<Head extends ResultHead, Row extends ResultRow> extends AbstractExecution implements SearchableInputStream{

	private static final long serialVersionUID = 2432654594849171913L;
	
	protected final List<Row> rows = new ArrayList<>();
	/**
	 * 这里应该的是能直接从数据库里读出字段的一个列(column)信息
	 */
	protected final List<Head> heads = new ArrayList<>();
	
	private int columnSize;
	private int headCount;
	private ResultHeadInfo[][] _heads;
	
//	protected AbstractResultStream(Executable executable) throws Exception {
//		super(executable);
//	}
	
	@Override
	public void buildHead(SelectedFieldCollection master) {
		
		/*
		 * 要如何对头部进行分组处理呢？目前还不清楚，预留着
		 */
		for(SelectFragment sf : master.fields()){
			Head head = buildHead(sf);
			if(null != head && !head.disabled()){
				heads.add(head);
			}
		}
	}
	
	@Override
	public int getColumnSize() {
		return columnSize;
	}
	
	@Override
	public ResultHeadInfo[][] getHeads() {
		return _heads;
	}
	
	@Override
	public List<? extends ResultRow> getRows() {
		return rows;
	}
	
	protected abstract Head buildHead(SelectFragment sf);
	
		
	/**
	 * <pre>
	 * 这里是读取一整个表
	 * </pre>
	 */
	@Override
	public final void read(ResultSet rs) throws Exception{

		try{
			internalRead(rs);
		}finally{
			rs.close();
		}
		
	}
	
	protected abstract void internalRead(ResultSet rs) throws Exception;
	
	protected void beforeFlush(List<ResultHeadInfo> one){}
	
	@Override
	public void flush() throws Exception {
		/*
		 * TODO 这里严重的需要修改，因为这个方法在被一次读取的数据操作里可能会被执行多次的操作
		 * 这里要处理头部和数据内容，头部需要处理包括跨行跨列的情况
		 */
		
		//检查表格的宽度和表头的高度
		List<ResultHeadInfo> one = new ArrayList<>();//new ResultHeadInfo[heads.size()];
		//int point = 0;
		beforeFlush(one);
		
		GroupResultHead sameGroup = null, groupLast = null;;
		for(ResultHead head : heads){
			int colspan = head.getColspan();
			if(colspan > 1){
				columnSize += colspan;
				
				headCount = 2;
			}else{
				columnSize += 1;
			}
			
			String[] groups = head.group();
			if(null != groups && groups.length > 0){
				if(null != sameGroup){
					groupLast = sameGroup.tryAppend(groups, 0);
					if(null == groupLast){
						sameGroup = null;
					}else{
						sameGroup.children.add(head);
					}
				}
				
				if(null == sameGroup){
					sameGroup = new GroupResultHead(groups[0]);
					groupLast = sameGroup;
					for(int i = 1; i < groups.length; i++){
						GroupResultHead temp = new GroupResultHead(groups[i]);
					}
				}
				
			}else{
				one.add(head);
//				one[point++] = head;
				
				sameGroup = null;
			}
		}
		
		if(headCount > 1){
			//跨行了
			List<ResultHeadInfo> ltwo = new ArrayList<>();
			for(ResultHeadInfo head:one){
				head.setRowspan(headCount);
				List<ResultHeadInfo> child = head.children();
				if(null != child && !child.isEmpty()){
					head.setColspan(child.size());
					ltwo.addAll(child);
				}
			}
//			for(ResultHead head : heads){
//				head.setRowspan(headCount);
//				List<ResultHeadInfo> child = head.children();
//				if(null != child && !child.isEmpty()){
//					head.setColspan(child.size());
//					ltwo.addAll(child);
//				}
//			}
			
			_heads = new ResultHeadInfo[2][];
			_heads[0] = one.toArray(new ResultHeadInfo[one.size()]);
			_heads[1] = ltwo.toArray(new ResultHeadInfo[ltwo.size()]);
		}else{
			_heads = new ResultHeadInfo[1][];
			_heads[0] = one.toArray(new ResultHeadInfo[one.size()]);
		}
	}
	
	private class GroupResultHead implements ResultHeadInfo{
		private final String title;
		
		private GroupResultHead parent;
		private List<ResultHeadInfo> children = new ArrayList<>();
		private int deep = 0;
		private int rowspan=1;
		private int colspan=1;
		public GroupResultHead(String title){
			this.title = title;
		}
		
		public GroupResultHead tryAppend(String[] groups, int deep) {
			if(title.equals(groups[deep])){
				if(deep < groups.length){
					//for()
				}else{
					return this;
				}
			}
			return null;
		}

		@Override
		public int getColspan() {
			return children.size();
		}

		@Override
		public int getRowspan() {
			return 0;
		}

		@Override
		public String getTitle() {
			return title;
		}

		@Override
		public List<ResultHeadInfo> children() {
			return children;
		}

		@Override
		public void setRowspan(int rowspan) {
			this.rowspan=rowspan;
			
		}

		@Override
		public void setColspan(int colspan) {
			this.colspan=colspan;
		}
		
	}
}
